home *** CD-ROM | disk | FTP | other *** search
- ;HISTRSX.MAC 07/25/86 Jim Lopushinsky Meadowlark 403-435-6579
- ;
- ; Copyright (c) 1986 Jim Lopushinsky
- ;
- ; Requires Z80 processor and CP/M Plus
- ;
- ; A History command for CP/M+ similiar to Andrew McLean's BUFFER+,
- ; but much smaller and simpler. This RSX has the same features as
- ; BUFFER+, with the added feature of seperation of CCP and user history
- ; lines. The decrease in size is acheived by using CP/M 3's built in
- ; console input I/O redirection features that the CCP, SUBMIT, and GET
- ; uses to redirect console input to a text string in RAM. Thus, all the
- ; editting code that is in the BDOS is not duplicated here. The only
- ; intercept code is for ^W (scroll back), ^V (scroll ahead),
- ; ^L (list history lines). This RSX is safe to remove at any time
- ; by simply setting the remove flag. Although some ideas were lifted
- ; from BUFFER+, the code is all original. This RSX is quite safe to
- ; use beneath or on top of BYE or within Submit files (even nested).
- ;
- .z80
-
- buff_len equ 300 ; Length of buffer
- page_size equ 23 ; Lines to display before pause
-
- ctrlw equ 'W'-40h
- ctrlv equ 'V'-40h
- ctrll equ 'L'-40h
- ctrlx equ 'X'-40h
- ctrlk equ 'K'-40h
-
- ;..........
- ;
- ; RSX header
- ;
- dw 0,0,0
- jp ftest
- next: jp 0
- prev: dw 0
- remove: db 0ffh
- db 0
- db 'HIST '
- db 0,0,0
-
- ftest:
- ld a,c ; Get the function
- cp 60 ; RSX function?
- jr z,rsxtest ; Jump if could be for us
- ld a,(initf)
- or a ; Initialized?
- jr z,next ; Ignore if not
- ld a,c ; Get BDOS function
- cp 10 ; Get Line?
- jr nz,next ; Ignore if not
- ld a,e
- or d ; Using initialized DMA?
- jr z,next ; Ignore if using DMA
- ld hl,(scbbase)
- ld l,0bah ; Point to console redirected addr
- ld a,(hl)
- inc l
- or (hl) ; CONIN redirection?
- jr nz,next ; Ignore if redirection
- ld l,0b4h ; Point to CCP flags
- ld a,(hl)
- and 80h ; Isolate CCP active bit
- ld (ccpflag),a ; Save for redirection routines
- push de ; Save buffer address
- xor a
- ld (conchar),a ; Init for BIOS routines
- ld hl,0ffffh
- ld (cur_line),hl ; Init current line address
- call patch ; Patch BIOS
- call next ; Fill the buffer
- call unpatch ; Restore original BIOS vectors
- pop de ; Restore buffer address
- inc de ; Point to length
- ld a,(de)
- or a ; Anything there?
- ret z ; Ignore if empty
- ld c,a
- ld b,0 ; Set up BC = length
- inc de ; Point to start of text
- call add_line ; Add current line to storage
- ret
-
- ;......
- ;
- ; Here to initialize or unload previous HISTORY RSX
- ;
- ;
- rsxtest:
- ld a,(de) ; Get RSX function
- cp 56 ; Clear buffer function?
- jr z,is56
- cp 55 ; Our init function?
- jr nz,next ; Ignore if not
- is55:
- ld a,(initf)
- or a ; Already initilized?
- jr z,notinit ; Jump if not init.
- ld a,0ffh
- ld (remove),a ; Set remove flag
- inc a
- ld (initf),a ; Reset init flag
- ld de,delmsg
- ld c,9
- call next ; Say that we will die.
- xor a
- ret
-
- notinit:
- call next ; See if we are cloned
- or a
- ret z ; If cloned, just return
- ld (initf),a ; Set init flag
- xor a
- ld (remove),a ; Reset remove flag
- ld de,scbpb
- ld c,49
- call next ; Get SCB address
- ld (scbbase),hl
- ld l,68h ; Point to SCB wboot jump
- ld de,6 ; Vectors are 6 apart
- ld b,4 ; 4 vectors to mod
- ld a,21h ; LD H,nnnn op code
- modloop:
- ld (hl),a ; Change JP nnn to LD H,nnn
- add hl,de ; Bump offset
- djnz modloop
- ld hl,(1) ; Get BIOS wboot addr
- ld a,9
- call addhla ; Offset to CONOUT
- ld (xconout),hl ; Save for CONOUT calls
- ld de,histmsg
- ld c,9
- call next ; Say that we are active
-
- is56:
- ld hl,buff_start
- ld (next_free),hl ; Init next free addr
- ld hl,0
- ld (head),hl ; Init head pointer
- ld (tail),hl ; and tail pointer
- xor a
- ret
-
- ;..........
- ;
- ; BIOS intercept routines. Only called if patched
- ;
- wboot:
- ld sp,stack ; Insure valid stack
- call unpatch ; Unpatch vectors
- jp xwboot ; And on to BIOS
-
- const:
- ld a,(xpend) ; ^X pending?
- or a
- jr nz,consta
- ld a,(conchar) ; Pending command?
- jp z,xconst ; On to BIOS if not
- consta:
- or 0ffh ; Set to char ready
- ret
-
- conin:
- ld hl,xpend
- ld a,(hl)
- ld (hl),0 ; Reset ^X pending
- or a
- jr z,conin1
- ld a,ctrlx
- ret ; Clear line
- conin1:
- ld a,(conchar) ; Char pending?
- or a
- jr nz,ischar
- call xconin ; Get a char
- cp ctrlw ; ^W ?
- jr z,set_hist
- cp ctrlv ; ^V ?
- jr z,set_hist
- cp ctrll ; ^L ?
- ret nz
-
- set_hist:
- ld (conchar),a ; Save char
- ld (xpend),a ; Set ^X pending flag
- ld a,ctrlk ; Return ^K to clear to end of line
- ret
-
- ischar:
- cp ctrll ; Is it list history?
- jr z,listit
- xor a
- ld (count),a ; Init count
- ischara:
- ld a,(count) ; Get count of tries
- cp 100 ; Arbitrary maximum
- jr nc,conina ; Ignore if none
- inc a ; Bump count
- ld (count),a
- ld hl,(cur_line) ; Get current line addr
- inc hl ; Test for 0FFFFh
- ld a,h
- or l
- jr z,ischar1 ; Jump if first
- dec hl
- jr ischar3
- ischar1:
- ld a,(conchar) ; Get char
- cp ctrlw
- ld hl,(tail) ; Get first ^W recall
- jr z,ischar2
- ld hl,(head) ; Get first ^V recall
- ischar2:
- ld a,h
- or l ; Test for none
- jr nz,aheadok ; Onward if something in storage
- conina:
- ld a,(conchar) ; Get pending char
- call unpatch ; We will no longer intercept
- ret
- ischar3:
- ld a,(conchar) ; Get command
- cp ctrlw ; ^W ?
- jr z,backup
- inc hl
- inc hl ; point to next line addr
- ld e,(hl)
- inc hl
- ld d,(hl) ; Get next line addr
- ex de,hl
- ld a,h
- or l ; End of chain?
- jr nz,aheadok
- ld hl,(head) ; Circle to head
- aheadok:
- ld (cur_line),hl ; Save current line addr
- ld a,4
- call addhla ; Offset to CCP flag
- ld a,(ccpflag) ; Get CCP flag
- cp (hl) ; Same?
- jr nz,ischara ; Try again if not.
- inc hl
- inc hl ; Offset to 2nd text char
- ex de,hl
- ld hl,(scbbase) ; Get SCB addr
- ld l,0bah ; Point to conin redirection addr
- ld (hl),e
- inc hl
- ld (hl),d ; BDOS will now redirect console
- ; input from our command line
- xor a
- ld (conchar),a ; Reset for later
- dec de ; Back to first char
- ld a,(de)
- ret ; Return with first char
- backup:
- ld hl,(cur_line)
- ld e,(hl)
- inc hl
- ld d,(hl) ; Get PREV line addr
- ex de,hl
- ld a,h
- or l ; At start of chain?
- jr nz,aheadok
- ld hl,(tail)
- jr aheadok
-
- listit:
- xor a
- ld (count),a ; Init page size count
- ld hl,(head)
- ld (list_line),hl ; Init current list line
- list1:
- ld hl,(list_line) ; Get current list line
- ld a,h
- or l ; Done?
- jr z,list2
- ld a,4
- call addhla ; Offset to CCP flag
- ld a,(ccpflag) ; get ccp flag
- cp (hl) ; Same?
- inc hl ; Offset to text start
- call z,showline ; Print it on console
- ld hl,(list_line)
- inc hl
- inc hl ; Offset to NEXT addr
- ld e,(hl)
- inc hl
- ld d,(hl)
- ld (list_line),de ; Save next list line
- jr list1 ; And loop for more
- list2:
- call spaces ; Space over to current column
- xor a
- ld (conchar),a ; Reset console char
- jp conin
-
- ;........
- ;
- ; Turn up a new line and space over to current console column position
- ;
- spaces:
- push hl
- call crlf ; Turn up a new line
- ld hl,(scbbase)
- ld l,0b7h ; Point to current console column
- ld a,(hl)
- or a ; Zero ?
- jr z,space2
- ld b,a
- ld c,' ' ; Space
- space1:
- call conout ; output a space
- djnz space1
- space2:
- pop hl
- ret
-
- ;........
- ;
- ; Patch BIOS vectors
- ;
- patch:
- push bc
- push de
- ld hl,(1)
- ld de,xwboot
- ld bc,9
- ldir ; Save original BIOS vectors
- ld de,(1)
- ld hl,vwboot
- ld bc,9
- ldir ; Patch in intercept vectors
- pop de
- pop bc
- ret
-
- ;.........
- ;
- ; Restore original BIOS vectors
- ;
- unpatch:
- push de
- ld de,(1)
- ld hl,xwboot
- ld bc,9
- ldir ; Restore original vectors
- pop de
- ret
-
- xwboot: ds 3
- xconst: ds 3
- xconin: ds 3
-
- vwboot: jp wboot
- vconst: jp const
- vconin: jp conin
-
- conout:
- push hl
- push bc
- call 0
- xconout equ $-2
- pop bc
- pop hl
- ret
-
- ;.........
- ;
- ; Add a new line to line buffer area
- ;
- add_line:
- ld hl,(next_free) ; Get addr of free area
- add hl,bc ; Add in line length
- ld a,6
- call addhla ; Account for header
- push de ; Save source addr
- ld de,buff_end ; Get addr of end
- or a
- sbc hl,de ; Room left?
- jr c,buff_ok
- call fix_buff ; Delete first entry and shuffle
- ; things up.
- pop de ; Restore source addr
- jr add_line ; And try again
- buff_ok:
- ld hl,(tail) ; Get current tail addr
- ld a,h
- or l ; Anything there?
- jr nz,tailok
- ld hl,buff_start ; Start at beginning
- tailok:
- ld de,(next_free) ; Get free addr
- inc hl
- inc hl ; Offset to NEXT addr
- ld (hl),e
- inc hl
- ld (hl),d ; Save forward pointer
- ex de,hl
- dec de
- dec de
- dec de ; Back to PREV pointer
- ld (tail),hl ; Save new tail addr
- ld (hl),e
- inc hl
- ld (hl),d ; Save back pointer
- inc hl
- xor a
- ld (hl),a
- inc hl
- ld (hl),a ; Init new forward pointer
- inc hl
- ld a,(ccpflag) ; Get CCP flag
- ld (hl),a ; Init CCP flag
- inc hl ; Point to start of text
- pop de ; Get source addr
- ex de,hl ; For LDIR
- ldir ; Move it into place
- xor a
- ld (de),a ; Put in terminating zero
- inc de
- ld (next_free),de ; Update next free addr
- ld hl,(head) ; Get head addr
- ld a,h
- or l ; Null?
- ret nz ; Return if ok
- ld hl,(tail)
- ld (head),hl ; If first, make head = tail
- ld (hl),a
- inc hl
- ld (hl),a ; Zero first back pointer
- ret
-
- ;..........
- ;
- ; Delete first history line, and move things up
- ;
- fix_buff:
- ld hl,(head) ; Get head addr
- ld a,h
- or l
- ret z ; Return if nothing there
- inc hl
- inc hl ; Offset to NEXT addr
- ld e,(hl)
- inc hl
- ld d,(hl) ; Get addr of 2nd line
- ld a,d
- or e ; Is there 2nd line?
- jr nz,moveok
- ex de,hl
- ld (head),hl ; Zero head
- ld (tail),hl ; and tail
- ld hl,buff_start
- ld (next_free),hl ; Init next free addr
- ret
- moveok:
- push bc ; Save length
- ld hl,(head) ; Get head addr
- push de
- ex de,hl
- or a
- sbc hl,de ; Calc amount of move
- ld (movlen),hl ; Save it
- ld b,h
- ld c,l
- ld hl,buff_len ; Get storage length
- or a
- sbc hl,bc ; Calc length for LDIR
- ld b,h
- ld c,l
- ld hl,(head) ; Get target of move
- pop de
- ex de,hl ; Swap for LDIR
- ldir ; Move buffer down
- ld hl,(head)
- xor a
- ld (hl),a
- inc hl
- ld (hl),a ; Init PREV pointer
- inc hl
- fix_loop:
- ld e,(hl)
- inc hl
- ld d,(hl) ; Get NEXT pointer
- ld a,d
- or e ; At end?
- jr z,fix_done
- push hl
- ld hl,(movlen) ; Get move length
- ex de,hl
- or a
- sbc hl,de ; Calc new NEXT pointer
- ex de,hl
- pop hl
- ld (hl),d
- dec hl
- ld (hl),e ; Replace NEXT pointer
- ex de,hl
- dec de
- dec de
- ld (hl),e
- inc hl
- ld (hl),d ; Update PREV pointer
- inc hl
- jr fix_loop
- fix_done:
- dec hl
- dec hl
- dec hl
- ld (tail),hl ; Update new tail pointer
- ld hl,(next_free)
- ld de,(movlen)
- or a
- sbc hl,de ; Calc new next free addr
- ld (next_free),hl
- pop bc ; Restore BC
- ret
-
- ;.............
- ;
- ; Display a command line on console
- ;
- showline:
- push hl
- ld hl,count
- ld a,(hl) ; Get count
- inc (hl) ; Bump count
- cp page_size ; screen full?
- call z,new_page
- call spaces ; Turn up a new line and space over
- pop hl
- show1:
- ld a,(hl)
- or a ; At end?
- ret z
- inc hl
- ld c,a
- call conout ; Show the char
- jr show1
-
- ;.......
- ;
- ; Prompt with [more] message
- ;
- new_page:
- ld (hl),0 ; Init line count
- call crlf ; Turn up a new line
- ld hl,more
- call show1 ; Print [more]
- call xconin ; Get any char
- ld hl,backsp
- jr show1 ; Backspace over [more] and exit
-
- crlf:
- ld c,13
- call conout
- ld c,10
- jp conout
-
-
- addhla:
- add a,l
- ld l,a
- ret nc
- inc h
- ret
-
- ;............
- ;
- ; Data area
- ;
- delmsg: db 13,10,'History RSX removed$'
- histmsg: db 13,10,'History RSX active$'
- more: db '[more]',0
- backsp: db 13,' ',13,0
-
- xpend: ds 1 ; ^X pending flag
- head: dw 0 ; Address of head
- tail: dw 0 ; Address of tail
- scbbase: ds 2 ; Address of SCB
- scbpb: db 3ah
- db 0
- initf: db 0 ; Init flag
- conchar: db 0 ; Current console char
- cur_line: ds 2 ; Address of current line
- list_line: ds 2 ; Address of list line
- movlen: ds 2 ; Move length
- ccpflag: ds 1 ; CCP active flag
- count: ds 1 ; Count of max tries
- next_free: dw buff_start ; Address of free ram
- buff_start: ds buff_len ; Room for history lines
- buff_end equ $ ; Address of end
- ds 6 ; Temp stack during WBoot
- stack equ $
-
- end